package com.tool.emulator.mos6502.instrs;

import java.io.*;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Instr.java @author tl 2011-6-16
 */
public class Instr {
	public static final Instr[] instrs = Instrs.instrs;
	//<CODE>
	public static final int BRK = 0x0;
	public static final int ORA_IX = 0x1;
	public static final int ORA_ZPG = 0x5;
	public static final int ASL_ZPG = 0x6;
	public static final int PHP = 0x8;
	public static final int ORA_IMM = 0x9;
	public static final int ASL_ACC = 0xa;
	public static final int ORA_ABS = 0xd;
	public static final int ASL_ABS = 0xe;
	public static final int BPL = 0x10;
	public static final int BPL_REL = 0x10;
	public static final int ORA_IY = 0x11;
	public static final int ORA_ZPGX = 0x15;
	public static final int ASL_ZPGX = 0x16;
	public static final int CLC = 0x18;
	public static final int ORA_ABSY = 0x19;
	public static final int ORA_ABSX = 0x1d;
	public static final int ASL_ABSX = 0x1e;
	public static final int JSR = 0x20;
	public static final int JSR_ABS = 0x20;
	public static final int AND_IX = 0x21;
	public static final int BIT_ZPG = 0x24;
	public static final int AND_ZPG = 0x25;
	public static final int ROL_ZPG = 0x26;
	public static final int PLP = 0x28;
	public static final int AND_IMM = 0x29;
	public static final int ROL_ACC = 0x2a;
	public static final int BIT_ABS = 0x2c;
	public static final int AND_ABS = 0x2d;
	public static final int ROL_ABS = 0x2e;
	public static final int BMI = 0x30;
	public static final int BMI_REL = 0x30;
	public static final int AND_IY = 0x31;
	public static final int AND_ZPGX = 0x35;
	public static final int ROL_ZPGX = 0x36;
	public static final int SEC = 0x38;
	public static final int AND_ABSY = 0x39;
	public static final int AND_ABSX = 0x3d;
	public static final int ROL_ABSX = 0x3e;
	public static final int RTI = 0x40;
	public static final int EOR_IX = 0x41;
	public static final int EOR_ZPG = 0x45;
	public static final int LSR_ZPG = 0x46;
	public static final int PHA = 0x48;
	public static final int EOR_IMM = 0x49;
	public static final int LSR_ACC = 0x4a;
	public static final int JMP_ABS = 0x4c;
	public static final int EOR_ABS = 0x4d;
	public static final int LSR_ABS = 0x4e;
	public static final int BVC = 0x50;
	public static final int BVC_REL = 0x50;
	public static final int EOR_IY = 0x51;
	public static final int EOR_ZPGX = 0x55;
	public static final int LSR_ZPGX = 0x56;
	public static final int CLI = 0x58;
	public static final int EOR_ABSY = 0x59;
	public static final int EOR_ABSX = 0x5d;
	public static final int LSR_ABSX = 0x5e;
	public static final int RTS = 0x60;
	public static final int ADC_IX = 0x61;
	public static final int ADC_ZPG = 0x65;
	public static final int ROR_ZPG = 0x66;
	public static final int PLA = 0x68;
	public static final int ADC_IMM = 0x69;
	public static final int ROR_ACC = 0x6a;
	public static final int JMP_IND = 0x6c;
	public static final int ADC_ABS = 0x6d;
	public static final int ROR_ABS = 0x6e;
	public static final int BVS = 0x70;
	public static final int BVS_REL = 0x70;
	public static final int ADC_IY = 0x71;
	public static final int ADC_ZPGX = 0x75;
	public static final int ROR_ZPGX = 0x76;
	public static final int SEI = 0x78;
	public static final int ADC_ABSY = 0x79;
	public static final int ADC_ABSX = 0x7d;
	public static final int ROR_ABSX = 0x7e;
	public static final int STA_IX = 0x81;
	public static final int STY_ZPG = 0x84;
	public static final int STA_ZPG = 0x85;
	public static final int STX_ZPG = 0x86;
	public static final int DEY = 0x88;
	public static final int TXA = 0x8a;
	public static final int STY_ABS = 0x8c;
	public static final int STA_ABS = 0x8d;
	public static final int STX_ABS = 0x8e;
	public static final int BCC = 0x90;
	public static final int BCC_REL = 0x90;
	public static final int STA_IY = 0x91;
	public static final int STY_ZPGX = 0x94;
	public static final int STA_ZPGX = 0x95;
	public static final int STX_ZPGY = 0x96;
	public static final int TYA = 0x98;
	public static final int STA_ABSY = 0x99;
	public static final int TXS = 0x9a;
	public static final int STA_ABSX = 0x9d;
	public static final int LDY_IMM = 0xa0;
	public static final int LDA_IX = 0xa1;
	public static final int LDX_IMM = 0xa2;
	public static final int LDY_ZPG = 0xa4;
	public static final int LDA_ZPG = 0xa5;
	public static final int LDX_ZPG = 0xa6;
	public static final int TAY = 0xa8;
	public static final int LDA_IMM = 0xa9;
	public static final int TAX = 0xaa;
	public static final int LDY_ABS = 0xac;
	public static final int LDA_ABS = 0xad;
	public static final int LDX_ABS = 0xae;
	public static final int BCS = 0xb0;
	public static final int BCS_REL = 0xb0;
	public static final int LDA_IY = 0xb1;
	public static final int LDY_ZPGX = 0xb4;
	public static final int LDA_ZPGX = 0xb5;
	public static final int LDX_ZPGY = 0xb6;
	public static final int CLV = 0xb8;
	public static final int LDA_ABSY = 0xb9;
	public static final int TSX = 0xba;
	public static final int LDY_ABSX = 0xbc;
	public static final int LDA_ABSX = 0xbd;
	public static final int LDX_ABSY = 0xbe;
	public static final int CPY_IMM = 0xc0;
	public static final int CMP_IX = 0xc1;
	public static final int CPY_ZPG = 0xc4;
	public static final int CMP_ZPG = 0xc5;
	public static final int DEC_ZPG = 0xc6;
	public static final int INY = 0xc8;
	public static final int CMP_IMM = 0xc9;
	public static final int DEX = 0xca;
	public static final int CPY_ABS = 0xcc;
	public static final int CMP_ABS = 0xcd;
	public static final int DEC_ABS = 0xce;
	public static final int BNE = 0xd0;
	public static final int BNE_REL = 0xd0;
	public static final int CMP_IY = 0xd1;
	public static final int CMP_ZPGX = 0xd5;
	public static final int DEC_ZPGX = 0xd6;
	public static final int CLD = 0xd8;
	public static final int CMP_ABSY = 0xd9;
	public static final int CMP_ABSX = 0xdd;
	public static final int DEC_ABSX = 0xde;
	public static final int CPX_IMM = 0xe0;
	public static final int SBC_IX = 0xe1;
	public static final int CPX_ZPG = 0xe4;
	public static final int SBC_ZPG = 0xe5;
	public static final int INC_ZPG = 0xe6;
	public static final int INX = 0xe8;
	public static final int SBC_IMM = 0xe9;
	public static final int NOP = 0xea;
	public static final int CPX_ABS = 0xec;
	public static final int SBC_ABS = 0xed;
	public static final int INC_ABS = 0xee;
	public static final int BEQ = 0xf0;
	public static final int BEQ_REL = 0xf0;
	public static final int SBC_IY = 0xf1;
	public static final int SBC_ZPGX = 0xf5;
	public static final int INC_ZPGX = 0xf6;
	public static final int SED = 0xf8;
	public static final int SBC_ABSY = 0xf9;
	public static final int SBC_ABSX = 0xfd;
	public static final int INC_ABSX = 0xfe;
	public static final int RESET = 0x100;
	public static final int BRK_NMI = 0x101;
	public static final int BRK_HARD = 0x102;
	//</CODE>

	public final String name;
	public final int code;
	public final AddressingMethod addressingMethod;
	public final int opLen;
	public final int cycles;
	public final boolean addCycleWhenCrossPage;

	public Instr(String name, int code, AddressingMethod addressingMethod, int cycles,
	             boolean addCycleWhenCrossPage) {
		super();
		this.name = name;
		this.code = code;
		this.addressingMethod = addressingMethod;
		this.opLen = addressingMethod.getOpLen();
		this.cycles = cycles;
		this.addCycleWhenCrossPage = addCycleWhenCrossPage;
	}

	public static Instr get(int code) {
		return instrs[code];
	}

	public static int getOpLen(int code) {
		Instr instr = get(code);
		return instr == null ? 1 : instr.opLen;
	}

	public static void main(String[] args) throws Exception {
		File file = new File("src/" + Instr.class.getName().replace('.', '/') + ".java");
		BufferedReader in = new BufferedReader(new FileReader(file));
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		PrintWriter out = new PrintWriter(bout);
		for (; ; ) {
			String line = in.readLine();
			out.println(line);
			if (line.replace('\t', ' ').trim().toUpperCase().startsWith("//<CODE>"))
				break;
		}
		HashMap<String, AtomicInteger> map = new HashMap<String, AtomicInteger>();
		for (Instr instr : Instrs.instrs) if (instr != null) map.put(instr.name, new AtomicInteger(0));
		for (Instr instr : Instrs.instrs) if (instr != null) map.get(instr.name).incrementAndGet();
		for (Instr instr : Instrs.instrs) {
			if (instr != null) {
				if (map.get(instr.name).get() == 1 || instr.addressingMethod.getMethodName() == null)
					out.println("\tpublic static final int " + instr.name + " = 0x" + Integer.toHexString(instr.code) + ";");
				if (instr.addressingMethod.getMethodName() != null)
					out.println("\tpublic static final int " + instr.name + "_" + instr.addressingMethod.getMethodName().toUpperCase()
							+ " = 0x" + Integer.toHexString(instr.code) + ";");
			}
		}
		for (; ; ) {
			String line = in.readLine();
			if (line.replace('\t', ' ').trim().toUpperCase().startsWith("//</CODE>")) {
				out.println(line);
				break;
			}
		}
		for (; ; ) {
			String line = in.readLine();
			if (line == null)
				break;
			out.println(line);
		}
		in.close();
		out.close();
		FileOutputStream fout = new FileOutputStream(file);
		bout.writeTo(fout);
		fout.close();
	}

	public String toString() {
		return name;
	}
}
